﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ImaginaryNumber
{
    class ImaginaryNumber: IComparable
    {
        private double real;
        private double imaginary;

        public ImaginaryNumber(double real, double imaginary)
        {
            this.real = real;
            this.imaginary = imaginary;
        }

        public int CompareTo(object obj)
        {
            if (obj == null) 
            {
                throw new ArgumentNullException("You can`t compare null");
            }

            ImaginaryNumber otherNumber = obj as ImaginaryNumber;
            ImaginaryNumber number = new ImaginaryNumber(this.Real, this.Imaginary);

            double firstNumber = (double)number;
            double secondNumber = (double)otherNumber;

            return firstNumber.CompareTo(secondNumber);
        }

        public double Imaginary
        {
            get
            {
                return imaginary;
            }
            set
            {
                imaginary = value;
            }
        }

        public double Real
        {
            get
            {
                return real;
            }
            set
            {
                real = value;
            }
        }

        public static ImaginaryNumber operator +(ImaginaryNumber firstNumber,
            ImaginaryNumber secondNumber)
        {
            double real = firstNumber.Real + secondNumber.Real;
            double img = firstNumber.Imaginary + secondNumber.Imaginary;

            return new ImaginaryNumber(real, img);
        }

        public static ImaginaryNumber operator -(ImaginaryNumber firstNumber,
            ImaginaryNumber secondNumber)
        {
            double real = firstNumber.Real - secondNumber.Real;
            double img = firstNumber.Imaginary - secondNumber.Imaginary;

            return new ImaginaryNumber(real, img);
        }

        public static ImaginaryNumber operator *(ImaginaryNumber firstNumber,
            ImaginaryNumber secondNumber) 
        {
            double real = firstNumber.Real * secondNumber.Real -
                (firstNumber.Imaginary * secondNumber.Imaginary);
            double img = firstNumber.Real * secondNumber.Imaginary +
                firstNumber.Imaginary * secondNumber.Real;
            return new ImaginaryNumber(real, img);
        }

        public static ImaginaryNumber operator /(ImaginaryNumber firstNumber,
            ImaginaryNumber secondNumber) 
        {
            double real = (firstNumber.Real * secondNumber.Real +
                firstNumber.Imaginary * secondNumber.Imaginary) /
                (secondNumber.Real * secondNumber.Real + 
                secondNumber.Imaginary * secondNumber.Imaginary);

            double img = (firstNumber.Imaginary * secondNumber.Real -
                firstNumber.Real * secondNumber.Imaginary)/
                (secondNumber.Real * secondNumber.Real +
                secondNumber.Imaginary * secondNumber.Imaginary);

            return new ImaginaryNumber(real, img);
        }

        public override string ToString()
        {
            return string.Format("{0} + i{1}", this.Real, this.Imaginary);
        }

        public static implicit operator ImaginaryNumber(double number)
        {
            return new ImaginaryNumber(number, 0);
        }

        public static explicit operator Double (ImaginaryNumber number)
        {
            return Math.Sqrt(number.Real * number.Real +
                number.Imaginary * number.Imaginary);
        }

        public double this[int index] 
        {
            get 
            {
                if (index < 0 || index > 1)
                {
                    throw new IndexOutOfRangeException("There is no such element");
                }
                else 
                {
                    if (index == 0)
                    {
                        return this.Real;
                    }
                    else 
                    {
                        return this.Imaginary;
                    }
                }
            }
        }
    }
}
